package com.crawler.waf.utils;

import java.util.Date;
import java.util.Random;

import org.apache.commons.lang3.StringUtils;

import com.crawler.waf.config.WafProperties;
import com.crawler.waf.security.authens.UserToken;
import com.crawler.waf.support.Constants;

public class TokenManager {
	
	/**
	 * token保存前缀
	 */
	private static final String UC_TOKEN = "uc.token";
	
	/**
	 * ACCESS_TOKEN 前缀
	 */
	private static final String ACCESS_TOKEN = "access";
	
	/**
	 * REFRESH_TOKEN 前缀
	 */
	private static final String REFRESH_TOKEN = "refresh";
	
	/**
	 * 过期时间 分钟
	 */
	private static final int TOKEN_TIMEOUT = WafProperties.getPropertyForInteger("token.timeout", "7200");
	
	/**
	 * 生成token
	 * @param userId
	 * @param type
	 * @return
	 */
	public static UserToken generate(Long userId, String type){
		String tokenUserId = String.valueOf(userId);
		UserToken userToken = new UserToken();
		String accessToken = generateToken(tokenUserId);
		String refreshToken = generateToken(tokenUserId);
		Date expiresAt = new Date(System.currentTimeMillis() + TOKEN_TIMEOUT * 60 * 1000);
		userToken.setAccessToken(accessToken);
		userToken.setRefreshToken(refreshToken);
		userToken.setExpiresAt(expiresAt);
		userToken.setUserId(tokenUserId);
		userToken.setServerTime(new Date());
		if(Constants.AUTHORIZATION_TYPE_MAC.equals(type)){
			String macKey = getRandomString(10);
			userToken.setMacKey(macKey);
		}
		TokenManager.set(type, userToken);
		return userToken;
	}
	
	
	/**
	 * 设置token
	 * @param type
	 * @param userToken
	 */
	public static void set(String type, UserToken userToken){
		int seconds = (int) ((userToken.getExpiresAt().getTime() - System.currentTimeMillis()) / 1000);
		RedisManager.set(accessTokenKey(type, userToken.getAccessToken()), userToken, seconds);
		RedisManager.set(refreshTokenKey(type, userToken.getRefreshToken()), userToken.getAccessToken(), seconds);
	}
	
	/**
	 * 获取token
	 * @param type
	 * @param accessToken
	 * @return
	 */
	public static UserToken get(String type, String accessToken){
		return RedisManager.get(accessTokenKey(type, accessToken), UserToken.class);
	}
	
	/**
	 * 通过refresh获取Token
	 * @param type
	 * @param refreshToken
	 * @return
	 */
	public static UserToken findByRefreshToken(String type, String refreshToken){
		String accessToken = RedisManager.get(refreshTokenKey(type, refreshToken));
		if(StringUtils.isEmpty(accessToken)){
			return null;
		}
		return get(type, accessToken);
	}
	
	/**
	 * 删除
	 * @param type
	 * @param accessToken
	 */
	public static void remove(String type, String accessToken){
		RedisManager.del(accessTokenKey(type, accessToken));
	}
	
	/**
	 * Access Token key
	 * @param type
	 * @param accessToken
	 * @return
	 */
	private static String accessTokenKey(String type, String accessToken){
		return String.format("%s:%s:%s:%s", UC_TOKEN, type, ACCESS_TOKEN, accessToken);
	}
	
	/**
	 * Refresh Token Key
	 * @param type
	 * @param refreshToken
	 * @return
	 */
	private static String refreshTokenKey(String type, String refreshToken){
		return String.format("%s:%s:%s:%s", UC_TOKEN, type, REFRESH_TOKEN , refreshToken);
	}
	
	/**
	 * 生成token
	 * @return
	 */
	private static String generateToken(String userId){
		return (Encrypt.shortMd5(userId) + Encrypt.SHA256(getRandomString(8))).toUpperCase();
	}

	/**
	 * 获取指定长度随机字符串
	 * 
	 * @param length
	 * @return
	 */
	private static String getRandomString(int length) {
		String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
		StringBuffer sb = new StringBuffer();
		Random random = new Random();
		for (int i = 0; i < length; i++) {
			sb.append(CHARS.charAt(random.nextInt(CHARS.length())));
		}
		return sb.toString();
	}
}
